package com.ssy.lingxi.marketing.serviceimpl.component.coupon;

import com.querydsl.core.BooleanBuilder;
import com.querydsl.core.types.Projections;
import com.querydsl.core.types.dsl.CaseBuilder;
import com.querydsl.core.types.dsl.NumberExpression;
import com.querydsl.jpa.impl.JPAQuery;
import com.querydsl.jpa.impl.JPAQueryFactory;
import com.ssy.lingxi.common.constant.marketing.MerchantCouponTypeEnum;
import com.ssy.lingxi.common.constant.marketing.PlatformCouponTypeEnum;
import com.ssy.lingxi.marketing.entity.coupon.*;
import com.ssy.lingxi.marketing.model.constant.*;
import com.ssy.lingxi.marketing.model.dto.CountCouponDetailDTO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;

/**
 * 优惠券查询组件
 * @author yzc
 * @version 2.0.0
 * @date 2021/11/22
 */
@Slf4j
@Component
public class CouponQueryComponent {

    @Resource
    private JPAQueryFactory queryFactory;

    /**
     * 查询正在进行的商家优惠券
     * @param memberId 会员id
     * @param roleId 角色id
     * @return 返回结果
     */
    public List<MerchantCouponDO> selectMerchantCouponExecutingByMember(Long memberId, Long roleId) {
        return this.baseSelectMerchantCouponExecuting(memberId, roleId, null);
    }

    /**
     * 查询正在进行的商家优惠券
     * @param couponIds 优惠券id
     * @return 返回结果
     */
    public List<MerchantCouponDO> selectMerchantCouponExecutingById(List<Long> couponIds) {
        return this.baseSelectMerchantCouponExecuting(null, null, couponIds);
    }

    /**
     * 查询正在进行的商家优惠券
     * @param memberId 会员id
     * @param roleId 角色id
     * @param roleId 优惠券id
     * @return 返回结果
     */
    public List<MerchantCouponDO> baseSelectMerchantCouponExecuting(Long memberId, Long roleId, List<Long> couponIds) {
        QMerchantCouponDO merchantCouponDO = QMerchantCouponDO.merchantCouponDO;

        BooleanBuilder predicates = new BooleanBuilder();

        // 前台用户领券
        predicates.and(merchantCouponDO.getWay.eq(MerchantCouponGetWayEnum.FRONT.getCode()));
        // 非0元购买抵扣券
        List<Integer> typeList = Arrays.asList(MerchantCouponTypeEnum.COMMON.getCode(),
                MerchantCouponTypeEnum.CATEGORY.getCode(),
                MerchantCouponTypeEnum.BRAND.getCode(),
                MerchantCouponTypeEnum.COMMODITY.getCode());
        predicates.and(merchantCouponDO.type.in(typeList));

        // 正在进行
        predicates.and(merchantCouponDO.status.eq(MerchantCouponStatusEnum.EXECUTING.getCode()));

        // 当前时间在发券时间内
        long currentTimeMillis = System.currentTimeMillis();
        predicates.and(merchantCouponDO.releaseTimeStart.loe(currentTimeMillis));
        predicates.and(merchantCouponDO.releaseTimeEnd.goe(currentTimeMillis));

        if (Objects.nonNull(memberId) && Objects.nonNull(roleId)) {
            predicates.and(merchantCouponDO.memberId.eq(memberId));
            predicates.and(merchantCouponDO.roleId.eq(roleId));
        }

        if (!CollectionUtils.isEmpty(couponIds)) {
            predicates.and(merchantCouponDO.id.in(couponIds));
        }

        JPAQuery<MerchantCouponDO> queryJpaQuery = queryFactory.select(merchantCouponDO)
                .from(merchantCouponDO);

        queryJpaQuery.where(predicates);
        return queryJpaQuery.fetch();
    }

    /**
     * 查询正在进行的平台优惠券
     * @return 返回结果
     */
    public List<PlatformCouponDO> selectPlatformCouponExecuting() {
        return this.baseSelectPlatformCouponExecuting(null);
    }

    /**
     * 查询正在进行的平台优惠券
     * @return 返回结果
     */
    public List<PlatformCouponDO> selectPlatformCouponExecutingById(List<Long> ids) {
        return this.baseSelectPlatformCouponExecuting(ids);
    }

    public List<PlatformCouponDO> baseSelectPlatformCouponExecuting(List<Long> ids) {
        QPlatformCouponDO platformCouponDO = QPlatformCouponDO.platformCouponDO;

        BooleanBuilder predicates = new BooleanBuilder();
        // 前台用户领券
        predicates.and(platformCouponDO.getWay.eq(PlatformCouponGetWayEnum.FRONT.getCode()));
        // 非0元购买抵扣券
        predicates.and(platformCouponDO.type.eq(PlatformCouponTypeEnum.COMMON.getCode()));

        // 正在进行
        predicates.and(platformCouponDO.status.eq(PlatformCouponStatusEnum.EXECUTING.getCode()));

        // 当前时间在发券时间内
        long currentTimeMillis = System.currentTimeMillis();
        predicates.and(platformCouponDO.releaseTimeStart.loe(currentTimeMillis));
        predicates.and(platformCouponDO.releaseTimeEnd.goe(currentTimeMillis));

        if (!CollectionUtils.isEmpty(ids)) {
            predicates.and(platformCouponDO.id.in(ids));
        }

        JPAQuery<PlatformCouponDO> queryJpaQuery = queryFactory.select(platformCouponDO)
                .from(platformCouponDO);

        queryJpaQuery.where(predicates);
        return queryJpaQuery.fetch();
    }
    /**
     * 统计商家优惠券数量
     * @param couponIdList 商家优惠券id
     * @return 返回结果
     */
    public List<CountCouponDetailDTO> countMerchantCouponDetail(List<Long> couponIdList) {
        QMerchantCouponDetailDO merchantCouponDetailDO = QMerchantCouponDetailDO.merchantCouponDetailDO;
        // 已领取数量
        NumberExpression<Integer> obtainQuantity = new CaseBuilder().when(merchantCouponDetailDO.status.eq(MerchantCouponDetailStatusEnum.RECEIVE.getCode())).then(1).otherwise(0).sum().as("obtainQuantity");
        // 已使用数量
        NumberExpression<Integer> useQuantity = new CaseBuilder().when(merchantCouponDetailDO.status.eq(MerchantCouponDetailStatusEnum.USE.getCode())).then(1).otherwise(0).sum().as("useQuantity");
        // 过期数量
        NumberExpression<Integer> dueQuantity = new CaseBuilder().when(merchantCouponDetailDO.status.eq(MerchantCouponDetailStatusEnum.EXPIRE.getCode())).then(1).otherwise(0).sum().as("dueQuantity");
        List<CountCouponDetailDTO> countCouponDetailDTOList = queryFactory.select(
                Projections.bean(CountCouponDetailDTO.class,
                        merchantCouponDetailDO.coupon.id.as("couponId"),
                        obtainQuantity,
                        useQuantity,
                        dueQuantity
                ))
                .from(merchantCouponDetailDO)
                .where(merchantCouponDetailDO.coupon.id.in(couponIdList))
                .groupBy(merchantCouponDetailDO.coupon.id)
                .fetch();
        return countCouponDetailDTOList;
    }

    /**
     * 统计平台优惠券数量
     * @param couponIdList 商家优惠券id
     * @return 返回结果
     */
    public List<CountCouponDetailDTO> countPlatformCouponDetail(List<Long> couponIdList) {
        QPlatformCouponDetailDO platformCouponDetailDO = QPlatformCouponDetailDO.platformCouponDetailDO;

        // 已领取数量
        NumberExpression<Integer> obtainQuantity = new CaseBuilder().when(platformCouponDetailDO.status.eq(PlatformCouponDetailStatusEnum.RECEIVE.getCode())).then(1).otherwise(0).sum().as("obtainQuantity");
        // 已使用数量
        NumberExpression<Integer> useQuantity = new CaseBuilder().when(platformCouponDetailDO.status.eq(PlatformCouponDetailStatusEnum.USE.getCode())).then(1).otherwise(0).sum().as("useQuantity");
        // 过期数量
        NumberExpression<Integer> dueQuantity = new CaseBuilder().when(platformCouponDetailDO.status.eq(PlatformCouponDetailStatusEnum.EXPIRE.getCode())).then(1).otherwise(0).sum().as("dueQuantity");
        List<CountCouponDetailDTO> countCouponDetailDTOList = queryFactory.select(
                Projections.bean(CountCouponDetailDTO.class,
                        platformCouponDetailDO.coupon.id.as("couponId"),
                        obtainQuantity,
                        useQuantity,
                        dueQuantity
                ))
                .from(platformCouponDetailDO)
                .where(platformCouponDetailDO.coupon.id.in(couponIdList))
                .groupBy(platformCouponDetailDO.coupon.id)
                .fetch();
        return countCouponDetailDTOList;
    }
}

